#ifndef COLOR_H
#define COLOR_H

#include <cstdint>
#include <ostream>

namespace raster {

struct Color{
    uint8_t rgba[4] = {0, 0, 0, 0}; // r, g, b, a ranges in [0, 255]

    Color() : rgba{0, 0, 0, 0} {};
    Color(uint8_t rr, uint8_t gg, uint8_t bb, uint8_t aa = 255) : rgba{rr, gg, bb, aa} { }
    Color(const Color &c) {
        for (int i = 0; i < 4; i++) {
            rgba[i] = c.rgba[i];
        }
    }

    Color& operator=(const Color &c) {
        for (int i = 0; i < 4; i++) {
            rgba[i] = c.rgba[i];
        }
        return *this;
    }

    uint8_t& operator[](const int i) { return rgba[i]; }
    uint8_t r() const { return rgba[0]; }
    uint8_t g() const { return rgba[1]; }
    uint8_t b() const { return rgba[2]; }
    uint8_t a() const { return rgba[3]; }

    Color operator+(const Color& c) const {
        return Color(rgba[0] + c.rgba[0],
                        rgba[1] + c.rgba[1],
                        rgba[2] + c.rgba[2],
                        rgba[3] + c.rgba[3]);
    }

    Color operator*(const float s) const {
        Color res{};
        if (s > 1.0f || s < 0.0f) return res;
        for (int i = 0; i < 4; i++) {
            res.rgba[i] = static_cast<uint8_t>(res.rgba[i] * s);
        }
        return res;
    }

    Color& operator*=(const float s) {
        Color res(*this);
        *this = res * s;
        return *this;
    }

    friend std::ostream& operator<<(std::ostream& os, const Color& v) {
        return os << static_cast<int>(v.r()) << ", "
                  << static_cast<int>(v.g()) << ", "
                  << static_cast<int>(v.b()) << ", "
                  << static_cast<int>(v.a());
    }
};

/// linear interpolation of color
inline Color ColorLerp(const Color& c1, const Color& c2, float s){
    return c1 * (1 - s) + c2 * s;
}

}

#endif // COLOR_H
